package middlwares

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/yyangl/yoyo/application"
	"github.com/yyangl/yoyo/registry"
	"github.com/yyangl/yoyo/registry/etcd"
	"github.com/yyangl/yoyo/utils"
	"strings"
)

func init() {
	fmt.Printf("init")
	endpoints = make(map[string]*application.Point)
	reg, err := etcd.NewEtcdRegister(registry.DefaultAddr)
	if err != nil {
		fmt.Printf("etcd error")
		return
	}

	kvs, err := reg.GetService(utils.ResolveServiceRootKey())
	if err != nil {
		fmt.Errorf("get services error . err = %v\n", err)
		return
	}

	// send signal . when delete key close goroutine
	chs := make(map[string]chan interface{})

	for k, _ := range kvs {
		keys := strings.Split(k, "/")
		sName := keys[2]
		if _, ok := endpoints[sName]; !ok {
			ch := make(chan interface{})
			chs[sName] = ch
			endpoints[sName] = application.NewPoint()
			fmt.Printf("go watch !ok sName %s\n", sName)
			go watchService(sName, ch)
		}
		//go func() {
		//	app.register.Watch()
		//}()
	}
	go func(reg registry.Register) {
		for resp := range reg.Watch(utils.ResolveServiceRootKey()) {
			switch resp.Event {
			case registry.PUT:
				keys := strings.Split(resp.Key, "/")
				sName := keys[2]
				if _, ok := endpoints[sName]; !ok {
					ch := make(chan interface{})
					chs[sName] = ch
					endpoints[sName] = application.NewPoint()
					fmt.Printf("go watch !ok sName %s\n", sName)
					go watchService(sName, ch)
				}
			case registry.DELETE:
				//_ = p.Delete(resp.Key)
			}
		}

	}(reg)
}

func watchService(name string, ch chan interface{}) {
	reg, err := etcd.NewEtcdRegister(registry.DefaultAddr)

	if err != nil {
		return
	}
	kvs, err := reg.GetService(utils.ResolveService(name))
	p := endpoints[name]
	for k, v := range kvs {
		keys := strings.Split(k, "/")
		p.Append(keys[3], v)
	}
	fmt.Printf("watch service %s\n", name)
	for resp := range reg.Watch(utils.ResolveService(name)) {
		switch resp.Event {
		case registry.PUT:
			fmt.Printf("put service %s value %s\n", resp.Key, resp.Value)
			kvs := strings.Split(resp.Key, "/")
			p.Append(kvs[3], resp.Value)
		case registry.DELETE:
			kvs := strings.Split(resp.Key, "/")
			fmt.Printf("delete service %s\n", resp.Key)
			_ = p.Delete(kvs[3])
		}
	}
	select {
	case <-ch:
		fmt.Printf("%s server exit")
	}
}

var endpoints map[string]*application.Point

func LbMiddleware() gin.HandlerFunc {
	return func(ctx *gin.Context) {

	}
}
